Extend Tag
==========
Extend tag allows to extend template with content of other templates. Parent template will load **all**
tags of extended template and process them as if they were inserted in place of the ``extend`` tag
definition.
Extend tag can be nested within groups as well, but in that case only ``group`` and ``extend`` tags loaded from
extended template, other tags (lookup, vars, input, output) are ignored. Nested extend only supports `groups`_ filter.
.. list-table:: extend tag attributes
:widths: 10 90
:header-rows: 1
* - Attribute
- Description
* - `template`_
- OS path to template file or reference to template within TTP Templates repository
* - `inputs`_
- filter, comma separated list of input tag names to load
* - `groups`_
- filter, comma separated list of group tag names to load
* - `vars`_
- filter, comma separated list of template variables tag names to load
* - `lookups`_
- filter, comma separated list of lookup tag names to load
* - `outputs`_
- filter, comma separated list of output tag names to load
* - `macro`_
- name of macro function to pass template content through
template
--------
``template="path_string"``
``path_string`` (mandatory) - relative current working directory or absolute OS path to template file or reference to template within TTP Templates repository in a form of ``ttp://path/to/template`` path. Alternatively, OS path to file within ``TTP_TEMPLATES_DIR`` directory, where ``TTP_TEMPLATES_DIR`` is an environment variable.
**Example-1**
This template uses reference to a template within TTP templates repository to load additional groups for parsing below data::
vlan 1234
name some_vlan
!
vlan 910
name one_more
!
interface Gi1.100
description Some description 1
encapsulation dot1q 100
ip address 10.0.0.1 255.255.255.0
shutdown
!
interface Gi2
description Some description 2
ip address 10.1.0.1 255.255.255.0
!
Template content::
vlan {{ vlan }}
name {{ name }}
Where ``ttp://platform/test_platform_show_run_pipe_sec_interface.txt`` template content is::
interface {{ interface }}
description {{ description | re(".+") }}
encapsulation dot1q {{ dot1q }}
ip address {{ ip }} {{ mask }}
shutdown {{ disabled | set(True) }}
Results::
[
[
[
{
"description": "Some description 1",
"disabled": True,
"dot1q": "100",
"interface": "Gi1.100",
"ip": "10.0.0.1",
"mask": "255.255.255.0",
},
{
"description": "Some description 2",
"interface": "Gi2",
"ip": "10.1.0.1",
"mask": "255.255.255.0",
},
{"vlans": {"1234": {"name": "some_vlan"}, "910": {"name": "one_more"}}},
]
]
]
**Example-2**
This template extending groups from a file on local file system to parse this data::
vlan 1234
name some_vlan
!
vlan 910
name one_more
!
interface Gi1.100
description Some description 1
encapsulation dot1q 100
ip address 10.0.0.1 255.255.255.0
shutdown
!
interface Gi2
description Some description 2
ip address 10.1.0.1 255.255.255.0
!
Template content::
vlan {{ vlan }}
name {{ name }}
Where ``/templates/parse_interfaces.txt`` template content is::
interface {{ interface }}
description {{ description | re(".+") }}
encapsulation dot1q {{ dot1q }}
ip address {{ ip }} {{ mask }}
shutdown {{ disabled | set(True) }}
Results::
[
[
[
{
"description": "Some description 1",
"disabled": True,
"dot1q": "100",
"interface": "Gi1.100",
"ip": "10.0.0.1",
"mask": "255.255.255.0",
},
{
"description": "Some description 2",
"interface": "Gi2",
"ip": "10.1.0.1",
"mask": "255.255.255.0",
},
{"vlans": {"1234": {"name": "some_vlan"}, "910": {"name": "one_more"}}},
]
]
]
**Example-3**
This example demonstrates how to use ``extend`` tag withing groups.
Sample data::
router bgp 65100
!
router-id 1.1.1.1
!
neighbor 2.2.2.2 remote-as 65000
neighbor 2.2.2.3 remote-as 65001
Parent template is::
router bgp {{ bgp_as }}
neighbor {{ peer }} remote-as {{ asn }}
Where ``/template/bgp_params.txt`` content is::
router-id {{ rid }}
After parsing these results produced::
[[{'bgp_config': {'bgp_as': '65100',
'config': {'rid': '1.1.1.1'},
'peers': [{'asn': '65000', 'peer': '2.2.2.2'},
{'asn': '65001', 'peer': '2.2.2.3'}]}}]]
**Example-4**
This example demonstrates how to use ``extend`` tag and ``TTP_TEMPLATES_DIR`` to load templates.
Given this files structure::
C:
└───TTP_TEMPLATES
└───parse_vlans_template.txt
And having ``TTP_TEMPLATES_DIR`` set to ``C:\TTP_TEMPLATES\`` value, we can use this template
to refer to ``parse_vlans_template.txt`` file from within extend tag::
Where ``parse_vlans_template.txt`` content is::
vlan {{ vlan }}
name {{ name }}
inputs
------
``inputs="name1, name2, .. , nameN"``
This filter allows to form a comma separated list of input tags to load from extended template, identified by input tag name attribute.
groups
------
``groups="name1, name2, .. , nameN"`` or ``groups="1, 5, .. , N"``
This filter allows to form a comma separated list of groups to load from extended template, identified by group tag name attribute or group index. Group indexes counted from top group starting from 0.
vars
----
``vars="name1, name2, .. , nameN"``
This filter allows to form a comma separated list of template variable tags to load from extended template, identified by variables tag name attribute.
lookups
-------
``lookups="name1, name2, .. , nameN"``
This filter allows to form a comma separated list of lookup tags to load from extended template, identified by lookup tag name attribute.
outputs
-------
``outputs="name1, name2, .. , nameN"``
This filter allows to form a comma separated list of output tags to load from extended template, identified by output tag name attribute.
macro
-----
``macro="macro_name"``
Apply arbitrary Python function on template text content before embedding it into parent template.
.. warning:: macro uses python ``exec`` function to parse code payload without imposing any restrictions, hence it is dangerous to
run templates from untrusted sources as they can have macro defined in them that can be used to execute any arbitrary code on the system.
Macro function must accept single argument to hold embedded template string and must return string
with resulted template content.
**Example**
In this example we define macro function to append 4 spaces to embedded template content.
Template::
def indent(template_text):
# macro to indent each line of original template with 4 space characters
return "\\n".join(f" {line}" for line in template_text.splitlines())
Where file ``./assets/extend_vlan.txt`` content is::
vlan {{ vlan }}
name {{ name }}
After passing through macro final template content will look like::
def indent(data):
# macro to indent each line of original template with 4 space characters
return "\\n".join(f" {line}" for line in data.splitlines())
vlan {{ vlan }}
name {{ name }}
For this sample data::
# this data indented with 4 spaces
vlan 1234
name some_vlan
!
vlan 910
name one_more
!
Final template will produce results::
[
[{"vlans": {"1234": {"name": "some_vlan"}, "910": {"name": "one_more"}}}]
]